package com.service;

import static com.def.GenericDef.E_BIS_TOOL;
import static com.def.GenericDef.E_READ_NOT_FOUND;
import static com.def.GenericDef.E_XPTOOLOPE_INVALID_INPUT;
import static com.def.GenericDef.E_XPTOOLOPE_INVALID_NOTALLOW_SPACE;
import static com.def.GenericDef.E_XPTOOLOPE_NEW_TIMESTAMP_INVALIED;
import static com.def.GenericDef.RETURN_CODE_OK;
import static com.def.GenericDef.RETURN_CODE_SET_ERROR;
import static com.def.GenericDef.RETURN_CODE_UNKNOWN;
import static com.def.GenericDef.RETURN_MESG_OK;
import static com.def.GenericDef.TRX_OUT;
import static com.def.GenericDef.T_XPTOOLOPE;
import static com.def.GenericDef._NORMAL;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import com.dao.IBisToolDao;
import com.dao.IRetToolPtDao;
import com.dao.IRetToolStDao;
import com.icim.service.ICIMBaseService;
import com.model.Bis_tool;
import com.model.Ret_tool_pt;
import com.model.Ret_tool_st;
import com.rtnBean.SimpleRtnBeen;
import com.tx.Xptoolope.XptoolopeI;
import com.tx.Xptoolope.XptoolopeO;
import com.tx.Xptoolope.XptoolopeOA;
import com.tx.Xptoolope.XptoolopeOA2;
import com.util.MqOpe;
import com.util.Util;

@Scope("prototype")
@Service("XptoolopeService")
public class XptoolopeService extends ICIMBaseService{
	private static Logger logger = Logger.getLogger(XptoolopeService.class);
	private static String TX_NAME = T_XPTOOLOPE;
	
	private final char IN_FIND_BY_TOOL ='F';
	private final char IN_UDATE_BY_TOOL ='U';
	private final char IN_FIND_PORT_BY_TOOL ='P';
	
	private XptoolopeI inTrx ;
	private XptoolopeO outTrx ;
	private MqOpe mqOpe;
	
	private String gszMsgBuf = "";	
	private Timestamp gEvtTimestamp;
	
	@Autowired
	private IBisToolDao bisToolDao;
	
	@Autowired
	private IRetToolStDao retToolStDao;
	
	@Autowired
	private IRetToolPtDao RetToolPtDao;
	
	
	public String subMainProc(String strInMsg) {
		Session session = retToolStDao.getCrSession();

		long rtnCode = _NORMAL;
		String outMsg = null;
		gszMsgBuf = "";
		gEvtTimestamp = Util.getCurrentTimestamp();
		inTrx = new XptoolopeI();
		outTrx = new XptoolopeO();
		outTrx.setTrx_id(TX_NAME);
		outTrx.setRtn_code(String.valueOf(RETURN_CODE_SET_ERROR));
		outTrx.setType_id(TRX_OUT);
		mqOpe = new MqOpe();
		
    	try{
    		inTrx = (XptoolopeI) mqOpe.inStr2Obj(strInMsg, inTrx);
			logger.info("InTrx is " + strInMsg);
			
			rtnCode = subMainProc2(inTrx.getAction_flg().toCharArray()[0]);
			if (rtnCode != _NORMAL) {
				TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
				outTrx.setRtn_code(String.valueOf(rtnCode));
				outTrx.setRtn_mesg(gszMsgBuf);
			} else {
				outTrx.setRtn_code(String.valueOf(RETURN_CODE_OK));
				outTrx.setRtn_mesg(RETURN_MESG_OK);
				session.flush();
			}
    	}catch(Exception ex){
    		TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
    		outTrx.setRtn_mesg(ex.getMessage());
    		outTrx.setRtn_code(RETURN_CODE_UNKNOWN);
    		logger.error(Util.stackTraceToString(ex));
    	}finally{
    		outMsg = mqOpe.obj2Str(outTrx);
    		return outMsg; 
    	}
	}
	
	/**
	 * Real action type
	 * @param actionType
	 * @return
	 */
	private long subMainProc2(char actionType) {
		long lRc = _NORMAL;
		SimpleRtnBeen rtnBeen = new SimpleRtnBeen(_NORMAL);
		
		Bis_tool bis_tool = new Bis_tool();
		bis_tool = bisToolDao.get(inTrx.getTool_id());
		if(null == bis_tool){
			gszMsgBuf = "Not found in ["+Bis_tool.class.getSimpleName().toUpperCase()+"] with ["+inTrx.getTool_id()+"]";
			return E_BIS_TOOL + E_READ_NOT_FOUND;
		}
		
		switch (actionType)
		{
			case IN_FIND_BY_TOOL: {
				lRc = getToolStat();
				break;
			}
			case IN_UDATE_BY_TOOL: {
				lRc = updateToolStat();
				break;
			}
			case IN_FIND_PORT_BY_TOOL:{
				lRc = getPortInfo();
				break;
			}
			default:{
				gszMsgBuf = "Invalide type input: [" + actionType + "]";
				return E_XPTOOLOPE_INVALID_INPUT;
			}
		} 
		
		return lRc;
	}
	
	/**
	 * Query tool info
	 * @return
	 */
	public long getToolStat(){
		long lRc = _NORMAL;
		
		Ret_tool_st tool_st = new Ret_tool_st();
		List<XptoolopeOA> oary= new ArrayList<XptoolopeOA>();
		XptoolopeOA xptoolopeOA = new XptoolopeOA();
		
		tool_st = retToolStDao.get(inTrx.getTool_id());
		if(null == tool_st){
			outTrx.setTool_cnt(0);
			return lRc;
		}
		
		xptoolopeOA.setTool_id(tool_st.getTool_id_fk());
		xptoolopeOA.setTool_stat(tool_st.getTool_stat());
		xptoolopeOA.setTool_sub_stat(tool_st.getTool_sub_stat());
		xptoolopeOA.setTool_mode(tool_st.getEqpt_mode());
		xptoolopeOA.setPv_tool_stat(tool_st.getPv_eqpt_stat());
		xptoolopeOA.setPv_tool_sub_stat(tool_st.getPv_eqpt_sub_stat());
		xptoolopeOA.setEvt_usr(tool_st.getClm_usr());
		xptoolopeOA.setPv_evt_usr(tool_st.getPv_clm_usr());
		xptoolopeOA.setEvt_timestamp(tool_st.getClm_timestamp().toString());
		xptoolopeOA.setPv_evt_timestamp(tool_st.getPv_clm_timestamp().toString());
		xptoolopeOA.setLKeep_time(tool_st.getKeep_time());
		xptoolopeOA.setRemark(tool_st.getTool_note());
		
		oary.add(xptoolopeOA);
		outTrx.setOary(oary);
		outTrx.setTool_cnt(1);
		
		return lRc;
	}
	
	/**
	 * Update tool status
	 * @return
	 */
	public long updateToolStat(){
		long lRc = _NORMAL;
		Timestamp inTimestamp = Util.String2Timestamp(inTrx.getEvt_timestamp());
		int iDiffInteger = 0;

		//Check input
		if(null == inTrx.getTool_stat()){
			gszMsgBuf = "Not allow input space tool status";
			return E_XPTOOLOPE_INVALID_NOTALLOW_SPACE;			
		}else if (null == inTrx.getTool_sub_stat()){
//			gszMsgBuf = "Not allow input space tool sub status";
//			return E_XPTOOLOPE_INVALID_NOTALLOW_SPACE;	
		}else if (null == inTrx.getTool_mode()){
//			gszMsgBuf = "Not allow input space tool mode";
//			return E_XPTOOLOPE_INVALID_NOTALLOW_SPACE;
		}else if (null == inTrx.getEvt_usr()){
			gszMsgBuf = "Not allow input space user ID";
			return E_XPTOOLOPE_INVALID_NOTALLOW_SPACE;
		} 
		
		Ret_tool_st tool_st = new Ret_tool_st();
		tool_st = retToolStDao.get(inTrx.getTool_id());
		if(null == tool_st){
			//Add
			Ret_tool_st tool_st_new = new Ret_tool_st();
			
			tool_st_new.setTool_id_fk(inTrx.getTool_id());
			tool_st_new.setTool_stat(inTrx.getTool_stat());
			tool_st_new.setTool_sub_stat(inTrx.getTool_sub_stat());
			tool_st_new.setEqpt_mode(inTrx.getTool_mode());
			
			tool_st_new.setClm_usr(inTrx.getEvt_usr());
			tool_st_new.setClm_timestamp(inTimestamp);
			tool_st_new.setPv_clm_timestamp(tool_st_new.getClm_timestamp());
			tool_st_new.setKeep_time(0);
			tool_st_new.setTool_note(inTrx.getRemark());
			
			retToolStDao.save(tool_st_new);
		}else{
			//Update
			tool_st.setPv_eqpt_stat(tool_st.getTool_stat());
			tool_st.setPv_eqpt_sub_stat(tool_st.getTool_sub_stat());
			tool_st.setPv_clm_usr(tool_st.getClm_usr());
			tool_st.setPv_clm_timestamp(tool_st.getClm_timestamp());
			
			tool_st.setTool_stat(inTrx.getTool_stat());
			tool_st.setTool_sub_stat(inTrx.getTool_sub_stat());
			tool_st.setEqpt_mode(inTrx.getTool_mode());
			tool_st.setClm_usr(inTrx.getEvt_usr());
			tool_st.setClm_timestamp(inTimestamp);
			iDiffInteger = (int) Util.getDiffMin(tool_st.getPv_clm_timestamp(), tool_st.getClm_timestamp());
			if (iDiffInteger < 0) {
				gszMsgBuf = "New change time["
						+ tool_st.getClm_timestamp().toString()
						+ "] can't before than last change time["
						+ tool_st.getPv_clm_timestamp().toString() + "]!";
				return E_XPTOOLOPE_NEW_TIMESTAMP_INVALIED;
			}
			tool_st.setKeep_time(iDiffInteger);
			
			tool_st.setTool_note(inTrx.getRemark());
			
			retToolStDao.update(tool_st);
		}
		
		return lRc;
	}

	/**
	 * Get tool's port info
	 * @return
	 */
	private long getPortInfo(){
		long lRc = _NORMAL;
		List<Ret_tool_pt> ret_tool_ptList = new ArrayList<Ret_tool_pt>();
		XptoolopeOA xptoolopeOA = new XptoolopeOA();
		List<XptoolopeOA> xptoolopeOAList = new ArrayList<XptoolopeOA>();
		List<XptoolopeOA2>  xptoolopeOA2List = new ArrayList<XptoolopeOA2>();
		
		ret_tool_ptList = RetToolPtDao.getPortInfoByTool(inTrx.getTool_id());
		 
		if(!ret_tool_ptList.isEmpty()){
			for(Ret_tool_pt item :ret_tool_ptList ){
				XptoolopeOA2 xptoolopeOA2 = new XptoolopeOA2();
				xptoolopeOA2.setPort_id(item.getId().getPort_id());
				xptoolopeOA2.setPort_stat(item.getPort_stat());
				xptoolopeOA2.setPort_type(item.getPort_typ());
				xptoolopeOA2.setPort_change_timestamp(item.getPort_timestamp().toString());
				xptoolopeOA2List.add(xptoolopeOA2);
			}
			xptoolopeOA.setOary2(xptoolopeOA2List);
			xptoolopeOA.setPort_cnt(ret_tool_ptList.size());
			xptoolopeOAList.add(xptoolopeOA);

		}else{
			xptoolopeOA.setPort_cnt(0);
			xptoolopeOAList.add(xptoolopeOA);
		}
		outTrx.setOary(xptoolopeOAList);
		outTrx.setTool_cnt(1);
 
		return lRc;
	}

}
